import { BorderType } from "./borderType";
import { getX, getY, avgAndClamp } from "./internal/utils";

/**
 * 水平方向一维滤波（针对2D数组）
 */
function horizontalFilterArray(
  data: number[][],
  dest: number[][],
  width: number,
  height: number,
  radius: number,
  borderType: BorderType,
): void {
  for (let y = 0; y < height; y++) {
    const row = data[y];
    const destRow = dest[y];
    let sum = 0;
    let count = 0;

    // 初始化第一个窗口
    for (let kx = -radius; kx <= radius; kx++) {
      const cx = getX(kx, width, borderType);
      if (cx === -1) continue;

      sum += row[cx];
      count++;
    }

    destRow[0] = sum / count;

    // 滑动窗口
    for (let x = 1; x < width; x++) {
      // 移除左侧像素
      const leftX = x - 1 - radius;
      const cx = getX(leftX, width, borderType);
      if (cx !== -1) {
        sum -= row[cx];
        count--;
      }

      // 添加右侧像素
      const rightX = x + radius;
      const cx2 = getX(rightX, width, borderType);
      if (cx2 !== -1) {
        sum += row[cx2];
        count++;
      }

      destRow[x] = sum / count;
    }
  }
}

/**
 * 垂直方向一维滤波（针对2D数组）
 */
function verticalFilterArray(
  data: number[][],
  dest: number[][],
  width: number,
  height: number,
  radius: number,
  borderType: BorderType,
): void {
  for (let x = 0; x < width; x++) {
    let sum = 0;
    let count = 0;

    // 初始化第一个窗口
    for (let ky = -radius; ky <= radius; ky++) {
      const cy = getY(ky, height, borderType);
      if (cy === -1) continue;

      sum += data[cy][x];
      count++;
    }

    dest[0][x] = sum / count;

    // 滑动窗口
    for (let y = 1; y < height; y++) {
      // 移除上方像素
      const topY = y - 1 - radius;
      const cy = getY(topY, height, borderType);
      if (cy !== -1) {
        sum -= data[cy][x];
        count--;
      }

      // 添加下方像素
      const bottomY = y + radius;
      const cy2 = getY(bottomY, height, borderType);
      if (cy2 !== -1) {
        sum += data[cy2][x];
        count++;
      }

      dest[y][x] = sum / count;
    }
  }
}

/**
 * 对2D数组应用盒式滤波
 * @param data 输入的2D数组
 * @param options 滤波选项
 * @returns 滤波后的2D数组
 */
export function boxFilterArray(
  data: number[][],
  options: { radius: number; borderType?: BorderType },
): number[][] {
  const { radius, borderType = BorderType.REPLICATE } = options;

  if (radius < 0) {
    throw new Error("Radius must be non-negative");
  }

  if (radius === 0) {
    // 深拷贝数组
    return data.map((row) => [...row]);
  }

  const height = data.length;
  if (height === 0) return [];

  const width = data[0].length;
  if (width === 0) return [];

  // 验证输入数组的完整性
  for (let y = 0; y < height; y++) {
    if (data[y].length !== width) {
      throw new Error("All rows must have the same length");
    }
  }

  // 创建临时数组和结果数组
  const temp: number[][] = Array.from(
    { length: height },
    () => new Array(width),
  );
  const result: number[][] = Array.from(
    { length: height },
    () => new Array(width),
  );

  // 先水平滤波，再垂直滤波
  horizontalFilterArray(data, temp, width, height, radius, borderType);
  verticalFilterArray(temp, result, width, height, radius, borderType);

  return result;
}
